package com.define.commons.quartz.controller;

import com.define.commons.common.base.BaseController;
import com.define.commons.common.utils.RS;
import com.define.commons.quartz.contract.DirContract;
import com.define.commons.quartz.domain.Task;
import com.define.commons.quartz.service.TaskService;
import com.define.commons.quartz.utils.DynamicCompilerUtil;
import com.define.commons.quartz.utils.QuartzUtil;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.fastmybatis.core.query.param.PageParam;
import com.gitee.fastmybatis.core.query.param.SortParam;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotEmpty;
import java.io.File;
import java.util.List;


/**
 * @Author xiewenlong
 * @Date 2018/11/21 10:24
 */
@RestController
@RequestMapping("task")
@Api(description = "定时任务接口")
public class TaskController extends BaseController {

    @Autowired
    QuartzUtil quartz;
    @Autowired
    private TaskService taskService;

    @PostMapping("upload")
    @ApiOperation(value = "远程任务上传", notes = "远程定时任务上传")
    RS remoteTaskUpload(@NotEmpty MultipartFile file) throws Exception {
        //保存文件
        File taskFile = new File(DirContract.REMOTE_TASK_DIR + File.separator + file.getOriginalFilename());
        FileCopyUtils.copy(file.getBytes(), taskFile);
        //编译文件
        DynamicCompilerUtil.compiler(DirContract.REMOTE_TASK_DIR, DirContract.JAR_DIR);
        return RS.ok();
    }

    @GetMapping
    @ApiOperation(value = "定时任务列表", notes = "当前所有已加载到系统中的任务列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageIndex", value = "页号", defaultValue = "1", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "pageSize", value = "页大小", defaultValue = "20", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "sort", value = "排序字段", paramType = "query"),
            @ApiImplicitParam(name = "order", value = "排序方式", paramType = "query")
    })
    RS page(Task task, PageParam pageParam, SortParam sortParam){
        Query query = Query.build(task).addPaginationInfo(pageParam).addSortInfo(sortParam);
        List<Task> list = taskService.list(query);
        return new RS(list);
    }

    /**
     * 根据任务添加一个工作
     */
    @PostMapping
    @ApiOperation("添加定时任务")
    RS addTask(Task task) throws Exception {
        if(StringUtils.isEmpty(task.getJobGroupName())){
            task.setJobGroupName(QuartzUtil.DEFAULT_JOB_GROUP_NAME);
        }
        if(null != taskService.getByQuery(Query.build(task))){
            throw new RuntimeException("任务已存在！");
        }
        quartz.addJob(task);
        String state = quartz.getJobState(task.getJobName(), task.getJobGroupName());
        task.setStatus(state);
        taskService.save(task);
        return RS.ok();
    }

    /**
     * 获取Job状态
     */
    @GetMapping("state")
    @ApiOperation("获取任务执行状态")
    public RS getJobState(@ApiParam(value = "任务名称", required = true) @NotEmpty String jobName,
                          @ApiParam(value = "任务组名称", required = true) @NotEmpty String jobGroupName) throws Exception {
        String state = quartz.getJobState(jobName, jobGroupName);
        return new RS(state);
    }

    /**
     * 暂停所有任务
     */
    @GetMapping("pauseAll")
    @ApiOperation(value = "暂停所有任务", notes = "暂停所有正在执行的任务")
    public RS pauseAllJob() throws Exception {
        quartz.pauseAllJob();
        List<Task> tasks = taskService.list(new Query().setQueryAll(true));
        for (Task task:tasks) {
            refreshState(task);
        }
        return RS.ok();
    }

    /**
     * 暂停任务
     */
    @GetMapping("pause")
    @ApiOperation(value = "暂停任务", notes = "根据任务名称和任务组名暂停一个正在执行任务")
    public RS pauseJob(@ApiParam(value = "任务名称", required = true) @NotEmpty String jobName,
                       @ApiParam(value = "任务组名称", required = true) @NotEmpty String jobGroupName) throws Exception {
        Task task = Task.builder().jobName(jobName).jobGroupName(jobGroupName).build();
        quartz.pauseJob(task.getJobName(), task.getJobGroupName());
        task = taskService.getByQuery(Query.build(task));
        refreshState(task);
        return RS.ok();
    }

    /**
     * 恢复所有任务
     */
    @GetMapping("resumeAll")
    @ApiOperation(value = "恢复所有任务", notes = "恢复所有已暂停的任务")
    public RS resumeAllJob() throws Exception {
        quartz.resumeAllJob();
        List<Task> tasks = taskService.list(new Query().setQueryAll(true));
        for (Task task : tasks) {
            refreshState(task);
        }
        return RS.ok();
    }

    /**
     * 恢复某个任务
     */
    @GetMapping("resume")
    @ApiOperation(value = "恢复任务", notes = "根据任务名称和任务组名恢复一个已暂停的任务")
    public RS resumeJob(@ApiParam(value = "任务名称", required = true) @NotEmpty String jobName,
                        @ApiParam(value = "任务组名称", required = true) @NotEmpty String jobGroupName) throws Exception {
        Task task = Task.builder().jobName(jobName).jobGroupName(jobGroupName).build();
        quartz.resumeJob(task.getJobName(), task.getJobGroupName());
        task = taskService.getByQuery(Query.build(task));
        refreshState(task);
        return RS.ok();
    }

    /**
     * 删除某个任务
     */
    @DeleteMapping
    @ApiOperation(value = "删除任务", notes = "根据任务名称和任务组名删除一个已存在的任务")
    public RS deleteJob(@ApiParam(value = "任务名称", required = true) @NotEmpty String jobName,
                        @ApiParam(value = "任务组名称", required = true) @NotEmpty String jobGroupName) throws Exception {
        Task task = Task.builder().jobName(jobName).jobGroupName(jobGroupName).build();
        if(quartz.deleteJob(task.getJobName(), task.getJobGroupName())){
            taskService.deleteByQuery(Query.build(task));
            return RS.ok();
        }else {
            return new RS(500, "操作失败！");
        }
    }

    /**
     * 修改任务
     */
    @PutMapping
    @ApiOperation(value = "修改任务", notes = "根据任务信息和触发器信息修改一个已存在的任务")
    public RS modifyJob(Task task) throws Exception {
        quartz.modifyJob(task);
        task = taskService.getByQuery(Query.build(task));
        refreshState(task);
        return RS.ok();
    }

    /**
     * 刷新任务状态
     */
    private void refreshState(Task task) throws Exception{
        if(task != null){
            String state = quartz.getJobState(task.getJobName(), task.getJobGroupName());
            task.setStatus(state);
            taskService.update(task);
        }
    }
}
